"""
Mail backend (SMTP + IMAP)

This file is part of polyglot, etc.
"""

import datetime
import hashlib
import email
from email.message import EmailMessage
from email.parser import BytesParser, Parser
from email.policy import default
from smtplib import SMTP_SSL
from imaplib import IMAP4_SSL
from .support import Backend, Inbox, Message, Thread

class MailMessage(Message):
    def __init__(self, imap, msg, date, sender, subject):
        self.date = date
        self.sender = sender
        self.subject = subject
        self.imap = imap
        self.msg = msg

    @property
    def body(self):
        (typ, data) = self.imap.fetch(self.msg, "(RFC822)")
        message = email.message_from_bytes(data[0][1], policy=default)

        for part in message.walk():
            if part.get_content_type() == 'text/plain':
                return part.get_payload()

class MailInbox(Inbox):
    def __init__(self, backend):
        self.backend = backend
        self.imap = IMAP4_SSL(self.backend.config["School"])

    @property
    def threads(self):
        threads = []

        self.imap.login(self.backend.config["Username"], self.backend.config["Password"])
        self.imap.select()
        typ, data = self.imap.search(None, "ALL")
        for num in data[0].split()[-10:]:
            (typ, data) = self.imap.fetch(num, "body[header]")

            headers = BytesParser(policy=default).parsebytes(data[0][1])
            subject = headers["subject"] or "(No subject)"
            date = headers["date"] or "(No date)"
            from_display = headers["from"].addresses[0].username or headers["from"]
            
            threads += [Thread(hashlib.md5(data[0][1]).hexdigest(), [MailMessage(self.imap, num, date, from_display, subject)])]

        threads.reverse()
        return threads

    def send(self, to, subject, body):
        msg = EmailMessage()
        msg.set_content(body)
        msg["To"] = to
        msg["From"] = self.backend.config["Username"]
        msg["Subject"] = subject

        # TODO: error handling (how is this handled in the frontend?)
        mail = SMTP_SSL(self.backend.config["School"])
        mail.login(self.backend.config["Username"], self.backend.config["Password"])
        mail.send_message(msg, self.backend.config["Username"], to)
        mail.quit()

class MailBackend(Backend):
    Config = ["Username", "Password", "School"]

    def login(self, config):
        # TODO: confirm login
        # SMTP servers disconnect on idle, so always reconnect 
        self.config = config
        return True

    @property
    def inbox(self):
        return MailInbox(self)
